package intermediateCodeClass;

/*
    单个三地址代码单元
 */
public class MidCodeNode {
    private int index;
    private OperationEnum op;
    private Object arg1;
    private Object arg2;
    private Object result;

    public MidCodeNode(OperationEnum op, Object arg1, Object arg2, Object result) {
        this.op = op;
        this.arg1 = arg1;
        this.arg2 = arg2;
        this.result = result;
    }

    public MidCodeNode(OperationEnum op, Object arg1, Object result) {
        this.op = op;
        this.arg1 = arg1;
        this.result = result;
    }

    public MidCodeNode(OperationEnum op, Object arg1) {
        this.op = op;
        if (op == OperationEnum.GOTO) {
            this.result = arg1;
        } else {
            this.arg1 = arg1;
        }
    }

    public MidCodeNode(OperationEnum op) {
        this.op = op;
    }

    public void setIndex(int index) {
        this.index = index;
    }
//
//    @Override
//    public String toString() {
//        return op +
//                "\t\t\t" + arg1 +
//                "\t\t\t" + arg2 +
//                "\t\t" + result;
//    }

    public String toString() {
        if (op == OperationEnum.DECLA) {
            return "DECLA " + result + " : " + arg2 + " " + arg1;
        }
        if (op == OperationEnum.PARAM) {
            return "para " + result + ":" + arg2 + " " + ((boolean) arg1 ? "&" : "");
        }
        if (op == OperationEnum.CONST_START || op == OperationEnum.CONST_END) {
            return op.toString();
        }
        if (op == OperationEnum.CONST) {
            return "    const " + result + " = " + arg1;
        }
        if (op == OperationEnum.ASSIGN) {
            return result + "=" + arg1;
        }
        if (op == OperationEnum.WRITE
                || op == OperationEnum.READ) {
            return op + "(" + arg1 + ")";
        }
        if (op == OperationEnum.CALL) {
            if (arg1 == null) {
                return op + " " + result + " ";
            }
            return result + " = " + op + " " + arg1 + " ";
        }
        if (op == OperationEnum.LABEL) {
            return arg1.toString();
        }
        if (op == OperationEnum.NOT) {
            return result + "= not " + arg1;
        }
        if (op == OperationEnum.RECORD_START
                || op == OperationEnum.RECORD_END
                || op == OperationEnum.PROC_START
                || op == OperationEnum.PROC_END
                || op == OperationEnum.FUNC_START
                || op == OperationEnum.FUNC_END) {
            return arg1 + " " + op;
        }
        if (op == OperationEnum.TYPE_START
                || op == OperationEnum.TYPE_END
                || op == OperationEnum.VAR_START
                || op == OperationEnum.VAR_END
                || op == OperationEnum.PROGRAM_BODY_START
                || op == OperationEnum.PROGRAM_BODY_END
                || op == OperationEnum.PROGRAM_START
                || op == OperationEnum.PROGRAM_END
                || op == OperationEnum.SUB_PROGRAM_START
                || op == OperationEnum.SUB_PROGRAM_END) {
            return op.toString();
        }
        if (op == OperationEnum.ADD_NEW_RECORD_ELEMENT) {
            return "    " + result + ":" + arg1 + " " + arg2;
        }
        if (op == OperationEnum.GOTO) {
            if (arg1 == null) {
                //无条件跳转
                return "goto " + result;
            } else {
                return "if " + arg1 + " goto " + result;
            }
        }
        if (op == OperationEnum.EQUAL) {
            return result + " = " + arg1 + " equal " + arg2;
        }
        if (op == OperationEnum.NEW_TYPE) {
            return result + " = " + op + " " + arg1;
        }
        if (op == OperationEnum.RETURN)
            return "return " + arg1;
        return result + "=" + arg1 + ' ' + op + ' ' + arg2;
    }

    public String generalCode() {
        return op + " " + arg1 + " " + arg2 + " " + result;
    }

    public int getIndex() {
        return index;
    }

    public OperationEnum getOp() {
        return op;
    }

    public Object getArg1() {
        return arg1;
    }

    public Object getArg2() {
        return arg2;
    }

    public Object getResult() {
        return result;
    }
}
